﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using Abp.Extension.CodeGenerater.Setting;

namespace Abp.Extension.CodeGenerater.Utils
{
    public class CodeUtil
    {


        #region 服务API TS调用

        //TODO ts代码其他方法
        public static string CreateTsServiceCode(string tableName, string idType, IDictionary<string, string> entityAttrs)
        {
            StringBuilder sb = new StringBuilder();
            string className = CreateServiceName(ref tableName, "ts");

            sb.AppendLine("import * as moment from 'moment';");
            sb.AppendLine("import 'rxjs/Rx';");
            sb.AppendLine("import { Observable } from 'rxjs/Observable';");
            sb.AppendLine("import { Injectable, Inject, Optional, OpaqueToken } from '@angular/core';");
            sb.AppendLine("import { Http, Headers, Response, RequestOptionsArgs } from '@angular/http';");
            sb.AppendLine("import { ExceptionHandler, ResponseHandler } from './service-proxies.common';");
            sb.AppendLine("import { AppConsts } from '@shared/AppConsts';");
            sb.AppendLine("@Injectable()");
            sb.AppendLine($"export class {className}" + "{");
            sb.AppendLine("   private baseUrl: string = undefined;");
            sb.AppendLine("   constructor( @Inject(Http) private http: Http) {");
            sb.AppendLine("      this.baseUrl = AppConsts.remoteServiceBaseUrl;");
            sb.AppendLine("   }");

            string tsIdType = (idType == "long" || idType == "int" ? "number" : "string");
            //方法
            #region Delete
            sb.AppendLine($"   delete(id: number) Observable<{tsIdType}>" + "{");
            sb.AppendLine($"      let _url = this.baseUrl + '/api/services/app/{className.Replace("ServiceProxy", "")}/Delete?id=' + id;");
            sb.AppendLine("      let _content = '';");
            sb.AppendLine(@"return this.http.request(_url, {
                                body: _content,
                                method: 'delete',
                                headers: new Headers({
                                    'Content-Type': 'application/json; charset=UTF-8'
                                })
                            }).map(response => {
                                return this.processDelete(response);
                            }).catch((response: any, caight: any) => {
                                return ExceptionHandler.handler<" + tsIdType + @">(response, this.processDelete(response));
                            });");
            sb.AppendLine("   }");

            sb.AppendLine(@"protected processDelete(response: Response): number {
                                return ResponseHandler.process<" + tsIdType + @"> (response, (result) => {
                                    return result;
                                });
                            }");
            #endregion

            #region
            #endregion
            return sb.ToString();
        }

        private static string CreateServiceName(ref string tableName, string type = "c#")
        {
            var nameSpace = RuleInfo.FindSetting(AppSettingNames.AppSetting_NameSpace);

            var entityNameSuffix = RuleInfo.FindSetting(AppSettingNames.AppSetting_EntityNameSuffix);
            if (entityNameSuffix != null)
            {
                tableName = tableName + entityNameSuffix.Value;
            }

            tableName = tableName.Substring(0, 1).ToUpper() + tableName.Substring(1, tableName.Length - 1);
            string className =
                $"{tableName + (nameSpace.Value.Split('.')[nameSpace.Value.Split('.').Length - 1])}{(type == "c#" ? "AppService" : "ServiceProxy")}";
            return className;
        }

        #endregion

        #region 服务
        /// <summary>
        /// 
        /// </summary>
        /// <param name="nodeName"></param>
        /// <param name="idType"></param>
        /// <param name="entityAttrs"></param>
        /// <returns></returns>
        public static string CreateService(string nodeName, string idType, IDictionary<string, string> entityAttrs)
        {
            return BuildService(nodeName, entityAttrs, idType);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="tableName"></param>
        /// <param name="entityAttrs">
        /// 实体类的属性集合 key:name value:type
        /// </param>
        /// <param name="idType"></param>
        /// <returns></returns>
        private static string BuildService(string tableName, IDictionary<string, string> entityAttrs, string idType = "long")
        {
            StringBuilder sb = new StringBuilder();

            var nameSpace = RuleInfo.FindSetting(AppSettingNames.AppSetting_NameSpace);

            string className = CreateServiceName(ref tableName);

            sb.AppendLine("using System;");
            sb.AppendLine("using Abp.AutoMapper;");
            sb.AppendLine("using System.Collections.Generic;");
            sb.AppendLine("using System.Linq;");
            sb.AppendLine("using Abp.Application.Services;");
            sb.AppendLine("using Abp.Application.Services.Dto;");
            sb.AppendLine("using System.Data.Entity;");
            sb.AppendLine("using System.Threading.Tasks;");
            sb.AppendLine("using Abp.Domain.Repositories; ");
            sb.AppendLine("using Abp.Extensions;");
            sb.AppendLine("using Abp.UI;");
            sb.AppendLine("using Castle.Core.Internal;");
            sb.AppendLine("using MyCompanyName.AbpZeroTemplate;");

            sb.AppendLine("");
            sb.AppendLine("");
            sb.AppendLine($"namespace {nameSpace.Value}.Application");
            sb.AppendLine("{");

            #region 接口
            sb.AppendLine($"    public interface I{className}:IApplicationService");
            sb.AppendLine("    {");

            sb.AppendLine($"         Task<int> Delete(EntityDto<{idType}> input);");
            sb.AppendLine("");

            sb.AppendLine($"         Task<int> Update({tableName}InputDto input);");
            sb.AppendLine("");

            sb.AppendLine($"         Task<int> Add({tableName}InputDto input);");
            sb.AppendLine("");

            sb.AppendLine($"         Task<{tableName}OutputDto> Get(EntityDto<{idType}> input);");
            sb.AppendLine("");

            sb.AppendLine($"         Task<IList<{tableName}OutputDto>> GetList();");
            sb.AppendLine("");

            sb.AppendLine("    }");
            #endregion

            sb.AppendLine("");
            sb.AppendLine("");
            #region 实现

            sb.AppendLine($"    public class {className}:AbpZeroTemplateAppServiceBase,I{className}");
            sb.AppendLine("    {");
            sb.AppendLine("");

            var tableNameVar = tableName.Substring(0, 1).ToLower() + tableName.Substring(1, tableName.Length - 1);
            sb.AppendLine($"       private readonly IRepository<{tableName},{idType}> _{tableNameVar}Repository;");
            sb.AppendLine("");
            sb.AppendLine($"       public {className}(IRepository<{tableName},{idType}> {tableNameVar}Repository)");
            sb.AppendLine("        {");
            sb.AppendLine($"            _{tableNameVar}Repository={tableNameVar}Repository;");
            sb.AppendLine("        }");

            //删除
            sb.AppendLine("");
            sb.AppendLine("");
            sb.AppendLine($"        public async Task<int> Delete(EntityDto<{idType}> input)");
            sb.AppendLine("        {");
            sb.AppendLine($"           await _{tableNameVar}Repository.DeleteAsync(input.Id);");
            sb.AppendLine("            return input.Id;");
            sb.AppendLine("        }");
            //更新
            sb.AppendLine("");
            sb.AppendLine("");
            sb.AppendLine($"        public async Task<int> Update({tableName}InputDto input)");
            sb.AppendLine("        {");
            sb.AppendLine($"           var entity = await _{tableNameVar}Repository.GetAsync(input.Id);");
            sb.AppendLine($"           if(entity==null)");
            sb.AppendLine("           {");
            sb.AppendLine("               throw new UserFriendlyException(\"对象不存在\");");
            sb.AppendLine("           }");
            foreach (KeyValuePair<string, string> entityAttr in entityAttrs)
            {
                sb.AppendLine($"           entity.{entityAttr.Key} = input.{entityAttr.Key};");
            }
            sb.AppendLine($"           await _{tableNameVar}Repository.UpdateAsync(entity);");
            sb.AppendLine($"           return input.id;");
            sb.AppendLine("        }");
            //添加
            sb.AppendLine("");
            sb.AppendLine("");
            sb.AppendLine($"        public async Task<int> Add({tableName}InputDto input)");
            sb.AppendLine("        {");
            sb.AppendLine($"           var entity = input.MapTo<{tableName}>();");
            sb.AppendLine($"           var dbEntity = await _{tableNameVar}Repository.InsertAsync(entity);");
            sb.AppendLine($"           return dbEntity.id;");
            sb.AppendLine("        }");
            //获取单个
            sb.AppendLine("");
            sb.AppendLine("");
            sb.AppendLine($"        public async Task<{tableName}OutputDto> Get(EntityDto<{idType}> input)");
            sb.AppendLine("        {");
            sb.AppendLine($"           return await _{tableNameVar}Repository.GetAsync(input.Id);");
            sb.AppendLine("        }");
            //获取所有
            sb.AppendLine("");
            sb.AppendLine("");
            sb.AppendLine($"        public async Task<IList<{tableName}OutputDto>> GetList()");
            sb.AppendLine("        {");
            sb.AppendLine($"           return (await _{tableNameVar}Repository.GetListAsync()).MapTo<IList<{tableName}OutputDto>>();");
            sb.AppendLine("        }");

            sb.AppendLine("    }");
            #endregion
            sb.AppendLine("");
            sb.AppendLine("");
            #region Dto
            sb.AppendLine($"    [AutoMapTo(typeof({tableName}))] ");
            sb.AppendLine($"    public class {tableName}InputDto");
            sb.AppendLine("    {");
            foreach (KeyValuePair<string, string> attr in entityAttrs)
            {
                sb.AppendLine($"        public {attr.Value} {attr.Key}" + "{ get; set; }");
            }
            sb.AppendLine("    }");
            sb.AppendLine("");
            sb.AppendLine($"    [AutoMapFrom(typeof({tableName}))] ");
            sb.AppendLine($"    public class {tableName}OutputDto");
            sb.AppendLine("    {");
            foreach (KeyValuePair<string, string> attr in entityAttrs)
            {
                sb.AppendLine($"        public {attr.Value} {attr.Key}" + "{ get; set; }");
            }
            sb.AppendLine("    }");

            #endregion

            //命名空间结尾
            sb.AppendLine("}");
            return sb.ToString();
        }

        #endregion
    }
}
